/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lifeed;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.InvalidKeyException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
 *
 * @author Rossi
 */

public class CipherTools implements Serializable
{
	private static final long serialVersionUID = 3372196611419971724L;

	private SecretKey key;
	private transient Cipher DEScipher;

        private static InputStreamReader inReader = new InputStreamReader(System.in);
	private static BufferedReader bufReader = new BufferedReader(inReader);

	public CipherTools(String password) throws IllegalArgumentException
	{
		try
		{
			if (password.length() < 8)
				throw new IllegalArgumentException();
			DEScipher = Cipher.getInstance("DES");
			key = genKey(password);
		}
		catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		catch (NoSuchPaddingException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		catch (InvalidKeySpecException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
		catch (InvalidKeyException e)
		{
			e.printStackTrace();
			System.exit(0);
		}
	}

    private SecretKey genKey(String password) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException
    {
        DESKeySpec keySpec = new DESKeySpec(password.getBytes());
        SecretKeyFactory secret = SecretKeyFactory.getInstance("DES");
        return secret.generateSecret(keySpec);
    }

	/**
	 *
	 * @param obj
	 * @param key
	 * @return
	 * @throws IOException
	 */
	public byte[] encrypt(byte[] obj) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException
	{
		DEScipher.init(Cipher.ENCRYPT_MODE, key);
		return DEScipher.doFinal(obj);
	}

	/**
	 *
	 * @param encData
	 * @param key
	 * @return
	 * @throws IOException
	 */
	public byte[] decrypt(byte[] encData) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException
	{
		DEScipher.init(Cipher.DECRYPT_MODE, key);
		return DEScipher.doFinal( encData );
	}

        @SuppressWarnings("unchecked")
	public static File fileFromBytes(byte[] data) throws IOException
	{
		try
		{
			return(File)toObject(data);
		}
		catch(Exception e)
		{
			throw new IOException();
		}
	}

	public static byte[] toBytes(Object object) throws IOException
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(baos);
		oos.writeObject(object);

		return baos.toByteArray();
	}

      public static byte[] getBytes(Object obj) throws java.io.IOException{
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          ObjectOutputStream oos = new ObjectOutputStream(bos);
          oos.writeObject(obj);
          oos.flush();
          oos.close();
          bos.close();
          byte [] data = bos.toByteArray();
          return data;
      }

      public static Object toObject(byte[] bytes){
        Object object = null;
        try{
            object = new java.io.ObjectInputStream(new
                    java.io.ByteArrayInputStream(bytes)).readObject();
        }catch(java.io.IOException ioe){
            //java.util.logging.Logger.global.log(java.util.loggi ng.Level.SEVERE,
            //ioe.getMessage());
            ioe.printStackTrace();
        }catch(java.lang.ClassNotFoundException cnfe){
            //java.util.logging.Logger.global.log(java.util.loggi ng.Level.SEVERE,
            //cnfe.getMessage());
            cnfe.printStackTrace();
        }
        return object;
    }


          public static byte[] getBytesFromFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);

        // Get the size of the file
        long length = file.length();

        if (length > Integer.MAX_VALUE) {
            // File is too large
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }

        // Close the input stream and return bytes
        is.close();
        return bytes;
    }

/*        public static void main(String[] args)
	{
            try {
            System.out.println("cipheringTest");
            System.out.println("insert your key: ");
            String pass = bufReader.readLine();
            CipherTools CT = new CipherTools(pass);

            byte[] b = ("<settings>\n\t<rss url=\"http://rss.feedsportal.com/c/32275/f/438637/index.rss\" last_upd=\"09-07-2009 10:00\"/>\n</settings>").getBytes();

            String path = "." + File.separator + "Contents" + File.separator + "user0_settings.xml";
            File test = new File(path);
            FileOutputStream o = new FileOutputStream(test);
            o.write(b);
            o.close();
            System.out.println("source file: "+test.toString());

            byte[] a = getBytesFromFile(test);
            System.out.println("byte[] in chiaro: "+new String(a));

            byte[] c = CT.encrypt(getBytesFromFile(test));
            System.out.println("byte[] cifrati: "+new String(c));

            File cryp = new File("." + File.separator + "Contents" + File.separator + "user0_settingsCIPHER.xml");
            if(!cryp.exists())
            cryp.createNewFile();

            FileOutputStream out = new FileOutputStream(cryp);
            out.write(c);
            out.close();

            System.out.println("cipher file: "+cryp.toString());

            //byte[] p = CT.decrypt(toBytes(cryp)); //voglio decifrare un file:: errore
            //questo toBytes() non mi convince
            byte[] p = CT.decrypt(getBytesFromFile(cryp));
            //byte[] p = CT.decrypt(c); //decifro solo l'array di byte
            System.out.println("byte[] decifrati: "+new String(p));

            File decryp = new File("." + File.separator + "Contents" + File.separator + "user0_settingsDECIPHER.xml");
            if(!decryp.exists())
            decryp.createNewFile();

            FileOutputStream outd = new FileOutputStream(test);
            outd.write(p);
            outd.close();

            System.out.println("decipher file: "+test.toString());
          }

            catch(Exception e) {
                e.printStackTrace();
            }

            }*/

        public static void main(String[] args)
    	{
            try {
            System.out.println("cipheringTest");
            System.out.println("insert your key: ");
            String pass = bufReader.readLine();
            CipherTools CT = new CipherTools(pass);

            String path = "." + File.separator + "Contents" + File.separator + "applicationnode_settings.xml";
            File test = new File(path);
            byte[] plainT = getBytesFromFile(test);

            System.out.println("byte[] in chiaro: "+new String(plainT));

            byte[] c = CT.encrypt(plainT);
            System.out.println("byte[] cifrati: "+new String(c));

            FileOutputStream out = new FileOutputStream(test);
            out.write(c);
            out.close();

            //byte[] p = CT.decrypt(getBytesFromFile(test));
            //System.out.println("byte[] decifrati: "+new String(p));

            //FileOutputStream outd = new FileOutputStream(test);
            //outd.write(p);
            //outd.close();

            //System.out.println("decipher file: "+new String(p));
          }

            catch(Exception e) {
                e.printStackTrace();
            }

            }
}
